package com.sparkseries.common.log.logProducer;

import java.util.concurrent.ThreadFactory;

import com.alibaba.nacos.common.utils.ThreadFactoryBuilder;
import com.sparkseries.common.log.domain.BaseLog;
import com.sparkseries.common.util.redis.RedisKeys;
import com.sparkseries.common.util.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;

import java.util.concurrent.*;

/**
 * 日志生产者类，负责将系统日志保存到 Redis 中。
 * TODO LogUtils整合一下
 */
@Component
@Slf4j
public class LogProducer {
    @Resource
    private RedisUtils redisUtils;

    // 线程池核心线程数
    private static final int CORE_POOL_SIZE = 5;
    // 线程池最大线程数
    private static final int MAX_POOL_SIZE = 200;
    // 线程空闲时间
    private static final long KEEP_ALIVE_TIME = 0L;
    // 时间单位
    private static final TimeUnit TIME_UNIT = TimeUnit.MILLISECONDS;
    // 任务队列容量
    private static final int QUEUE_CAPACITY = 1024;

    private final ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
            .nameFormat("log-producer")
            .build();

    private final ExecutorService pool = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME,
            TIME_UNIT,
            new LinkedBlockingQueue<>(QUEUE_CAPACITY),
            namedThreadFactory,
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    /**
     * 将日志保存到 Redis 中，采用异步方式执行。
     *
     * @param baseLog 要保存的系统日志对象
     */
    @Async
    public void saveLog(BaseLog baseLog) {
        if (baseLog == null) {
            log.warn("传入的日志对象为 null，将忽略该保存操作。");
            return;
        }
        pool.submit(() -> {
            try {
                redisUtils.leftPush(RedisKeys.getLogKey(),baseLog);
                log.info("日志保存到 Redis 成功，日志信息：{}", baseLog);
            } catch (Exception e) {
                log.error("日志保存到 Redis 失败，日志信息：{}", baseLog, e);
            }
        });
    }
}